/*
author:chenjunu
school:NWPU
*/

#include <iostream>
#include <mutex>
#include <vector>
#include <functional>
#include <thread>
#include <queue>
#include <stdio.h>
using namespace std;

class threadPool {
private:
    static threadPool* pool;
    static once_flag flag1;

    threadPool(int num) : stop(false) {
        for (int i = 0; i < num; i++) {
            threads.emplace_back([this, i]() {
                while (1) {
                    unique_lock<mutex> lock(this->mtx);
                    cv.wait(lock, [this]() { return !tasks.empty() || stop; });

                    if (stop && tasks.empty()) {
                        printf("第%d号线程退出！\n", i);
                        return;
                    }

                    function<void()> task(move(tasks.front()));
                    tasks.pop();
                    lock.unlock();
                    task();
                }
                });
        }
    };

    threadPool(const threadPool&) = delete;
    threadPool& operator=(const threadPool&) = delete;

    vector<thread> threads;
    queue<function<void()>> tasks;
    mutex mtx;
    bool stop;
    condition_variable cv;

public:
    // 添加任务
    template<class F, class... Args>
    void enqueue(F&& f, Args&&... args) {
        function<void()> task = bind(forward<F>(f), forward<Args>(args)...); // 修正参数包展开
        {
            unique_lock<mutex> lock(mtx);
            tasks.emplace(move(task));
        }
        cv.notify_one();
    }

    ~threadPool() {
        {
            unique_lock<mutex> lock(mtx);
            stop = true;
        }
        cv.notify_all();
        for (auto& it : threads) {
            it.join();
        }
    }

    static threadPool* getInstace(int num) {
        call_once(flag1, [num]() { pool = new threadPool(num); });
        return pool;
    }

    static void destoryPool() {
        delete pool;
        pool = nullptr;
    }
};

// 静态成员定义
threadPool* threadPool::pool = nullptr;
once_flag threadPool::flag1;

int main() {
    threadPool* pool = threadPool::getInstace(3);

    for (int i = 0; i < 5; i++) {
        pool->enqueue([i]() {
            printf("task %d is working\n", i); // 修正换行符
            this_thread::sleep_for(chrono::seconds(1));
            });
    }

    // 等待任务完成
    this_thread::sleep_for(chrono::seconds(6));
    pool->destoryPool();
    return 0;
}